﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Resources;
using System.IO;
using wBooks.Entity;
using System.Windows.Media;
using System.Xml.Linq;

namespace wBooks
{
    public partial class ReadBook : PhoneApplicationPage
    {
        IApplicationBarIconButton previousButton;

        public ReadBook()
        {
            InitializeComponent();
            this.previousButton = this.ApplicationBar.Buttons[0] as IApplicationBarIconButton;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            // Respect the saved settings
            this.ApplicationBar.ForegroundColor = Sessions.TextColor.Value;
            this.LayoutRoot.Background = new SolidColorBrush(Sessions.PageColor.Value);
            this.Document.Foreground = this.Footer.Foreground =
              new SolidColorBrush(Sessions.TextColor.Value);
            this.Document.FontSize = Sessions.TextSize.Value;
            this.Document.FontFamily = new FontFamily(Sessions.Font.Value);
            this.Document.ResentBook = Sessions.CurrentBook.Value;

            if (NavigationContext.QueryString.ContainsKey("bName"))
            {
                string bName = NavigationContext.QueryString["bName"];

                if (this.Document.Text == null)
                {
                    // Load the book as one big string from the included file
                    this.Document.Text = XmlHelper.LoadBook(bName);
                    UpdatePagination();
                }
                else if (this.State.ContainsKey("TextSize"))
                {
                    if (((int)this.State["TextSize"] != Sessions.TextSize.Value ||
                     (string)this.State["Font"] != Sessions.Font.Value))
                    {
                        // If the font family or size changed, the book needs to be repaginated
                        UpdatePagination();
                    }
                    else if ((Color)this.State["TextColor"] != Sessions.TextColor.Value)
                    {
                        // If only the color changed, simply re-render the current page
                        this.Document.RefreshCurrentPage();
                    }
                }
            }
            else if(Sessions.CurrentBook.Value != null)
            {
                string bName = Sessions.CurrentBook.Value;

                if (this.Document.Text == null)
                {
                    // Load the book as one big string from the included file
                    this.Document.Text = XmlHelper.LoadBook(bName);
                    UpdatePagination();
                }
                else if (this.State.ContainsKey("TextSize"))
                {
                    if (((int)this.State["TextSize"] != Sessions.TextSize.Value ||
                     (string)this.State["Font"] != Sessions.Font.Value))
                    {
                        // If the font family or size changed, the book needs to be repaginated
                        UpdatePagination();
                    }
                    else if ((Color)this.State["TextColor"] != Sessions.TextColor.Value)
                    {
                        // If only the color changed, simply re-render the current page
                        this.Document.RefreshCurrentPage();
                    }
                }
            }

            // Remember the current text settings so we can detect if they
            // were changed when returning from the settings page
            this.State["TextSize"] = Sessions.TextSize.Value;
            this.State["Font"] = Sessions.Font.Value;
            this.State["TextColor"] = Sessions.TextColor.Value;
            this.State["CurrentBook"] = Sessions.CurrentBook.Value;
        }

        protected override void OnBackKeyPress(CancelEventArgs e)
        {
            base.OnBackKeyPress(e);

            // If the page/chapter jump panel is open, make the back button close it
            if (this.JumpPanel.Visibility == Visibility.Visible)
            {
                e.Cancel = true;
                CloseJumpPanel();
            }
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);

            // Treat any tap as a page advance, 
            // unless the page/chapter jump panel is open
            if (this.JumpPanel.Visibility == Visibility.Collapsed)
            {
                this.Document.ShowNextPage();
                RefreshFooter();
            }
        }

        void UpdatePagination()
        {
            this.Document.UpdatePagination(delegate()
            {
                // Now that the book has been repaginated, refresh some UI
                // on the main thread
                this.Dispatcher.BeginInvoke(delegate()
                {
                    // Move to the page we were previously on based on the character index
                    // in the string (because the old page numbers are now meaningless)
                    this.Document.ShowPageWithCharacterIndex(
                      Sessions.CurrentCharacterIndex.Value);

                    RefreshFooter();

                    /*// Fill the chapters list box based on the current page numbers
                    this.ChaptersListBox.Items.Clear();
                    for (int i = 0; i < this.Document.Chapters.Count; i++)
                    {
                        this.ChaptersListBox.Items.Add(new KeyValuePair<string, string>(
                          "Chapter " + (i + 1),                    // Title
                          this.Document.Chapters[i].ToString("N0") // Page number
                        ));
                    }*/
                });
            });
        }

        void RefreshFooter()
        {
            // Because this is called whenever the page is changed, this is a good
            // spot to store the current spot in the book
            Sessions.CurrentCharacterIndex.Value = this.Document.CurrentCharacterIndex;
            this.Footer.Text = this.Document.CurrentPage.ToString("N0") + " / " +
                               this.Document.TotalPages.ToString("N0");
            this.previousButton.IsEnabled = (this.Document.CurrentPage > 1);
        }

        void OpenJumpPanel()
        {
            this.JumpPanel.Visibility = Visibility.Visible;
            this.ApplicationBar.IsVisible = false;
            // Fill the text box with the current page number
            // (without thousands separator)
            this.PageTextBox.Text = this.Document.CurrentPage.ToString();
            // Temporarily support landscape hardware keyboards
            this.SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;
        }

        void CloseJumpPanel()
        {
            this.JumpPanel.Visibility = Visibility.Collapsed;
            this.ApplicationBar.IsVisible = true;
            this.SupportedOrientations = SupportedPageOrientation.Portrait;
        }

        /*
        void ChaptersListBox_SelectionChanged(object sender,
                                              SelectionChangedEventArgs e)
        {
            if (this.ChaptersListBox.SelectedIndex >= 0)
            {
                // Jump to the selected page
                this.Document.ShowPage(
                  this.Document.Chapters[this.ChaptersListBox.SelectedIndex]);

                RefreshFooter();

                // Clear the selection so consecutive taps on the same item works
                this.ChaptersListBox.SelectedIndex = -1;

                // Delay the closing of the panel so OnMouseLeftButtonUp
                // doesn't advance the page
                this.Dispatcher.BeginInvoke(delegate() { CloseJumpPanel(); });
            }
        }*/

        void PageTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            this.PageTextBox.SelectAll();
        }

        void PageTextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            // Make pressing Enter do the same thing as tapping "Go"
            if (e.Key == Key.Enter)
                GoButton_Click(this, null);
        }

        void GoButton_Click(object sender, RoutedEventArgs e)
        {
            // If the page number is valid, jump to it
            int pageNumber;
            if (int.TryParse(this.PageTextBox.Text, out pageNumber))
            {
                this.Document.ShowPage(pageNumber);
                RefreshFooter();
                CloseJumpPanel();
            }
        }

        void PreviousButton_Click(object sender, EventArgs e)
        {
            this.Document.ShowPreviousPage();
            RefreshFooter();
        }

        void JumpButton_Click(object sender, EventArgs e)
        {
            OpenJumpPanel();
        }

        void SettingsButton_Click(object sender, EventArgs e)
        {
            this.NavigationService.Navigate(new Uri("/SettingsPage.xaml", UriKind.Relative));
        }
    }
}